package cc.linker.steplink.crm.merchanth5.service;

import cc.linker.steplink.crm.commons.FeeConstants;
import cc.linker.steplink.crm.commons.TradeTypeConstants;
import cc.linker.steplink.crm.commons.constant.WcPayConstant;
import cc.linker.steplink.crm.commons.domain.WxUser;
import cc.linker.steplink.crm.commons.form.FormRequest;
import cc.linker.steplink.crm.commons.http.HttpService;
import cc.linker.steplink.crm.commons.model.SystemProperties;
import cc.linker.steplink.crm.commons.model.WcPayProperties;
import cc.linker.steplink.crm.commons.utils.NumberUtils;
import cc.linker.steplink.crm.commons.utils.TransactionOrderUtil;
import cc.linker.steplink.crm.merchanth5.dao.EnrollActiveDao;
import cc.linker.steplink.crm.merchanth5.dao.MallBoomDao;
import cc.linker.steplink.crm.merchanth5.dao.MallDao;
import cc.linker.steplink.crm.merchanth5.dao.WxShareDao;
import cc.linker.steplink.crm.merchanth5.dao.acs.PurchaseProcessDao;
import cc.linker.steplink.crm.merchanth5.pojo.acs.AccountInfo;
import cc.linker.steplink.crm.merchanth5.pojo.acs.TradeInfo;
import cc.linker.steplink.crm.merchanth5.service.acs.PromoterClueService;
import cc.linker.steplink.crm.merchanth5.service.acs.PurchaseProcessService;
import cc.linker.steplink.crm.merchanth5.service.redis.ScoreActiveCacheService;
import cc.linker.steplink.crm.merchanth5.util.MD5;
import cc.linker.steplink.crm.merchanth5.util.ParamSignUtils;
import cc.linker.steplink.crm.response.GlobalException;
import com.alibaba.fastjson.JSON;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.scheduling.annotation.EnableAsync;
import org.springframework.stereotype.Service;
import org.springframework.util.StringUtils;

import java.io.IOException;
import java.math.BigDecimal;
import java.net.URISyntaxException;
import java.net.URLDecoder;
import java.sql.Timestamp;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.concurrent.TimeUnit;
import java.util.stream.Collectors;

@Slf4j
@Service
@EnableAsync
public class EnrollActiveService {

    private static final DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    private static final String ENROLL_KEY = "enroll:enrollactive_limit_option_";

    @Autowired
    private StringRedisTemplate stringRedisTemplate;
    @Autowired
    private EnrollActiveDao enrollActiveDao;
    @Autowired
    private PurchaseProcessDao purchaseProcessDao;
    @Autowired
    private MallDao mallDao;
    @Autowired
    private PurchaseProcessService purchaseProcessService;
    @Autowired
    private HttpService httpService;
    @Autowired
    private WcPayProperties wcPayProperties;
    @Autowired
    private MallBoomDao mallBoomDao;
    @Autowired
    private MaiBaoLaService maiBaoLaService;
    @Autowired
    private MallService mallService;
    @Autowired
    private OverViewInfoService overViewInfoService;
    @Autowired
    private WxShareDao wxShareDao;
    @Autowired
    private SystemProperties systemProperties;
    @Autowired
    private ScoreActiveCacheService scoreActiveCacheService;
    @Autowired
    private FormRequest formRequest;

    @Value("${system.scrm.formUrl}")
    private String formUrl;
    @Autowired
    private PromoterClueService promoterClueService;


    public Map<String, Object> getSignNew(Map<String, String> param) {

        String orderSource = param.get("orderSource");//来源 1：本系统；2：app
        String customerId = param.get("customerId");//用户Id
        String orderSn = param.get("orderSn");//唯一订单号
        String totalFee = param.get("totalFee");//付款金额（单位：分）
        String orgId = param.get("orgId");//机构Id
        String recordPid = param.get("recordPid");//推荐人用户Id
        String openId = param.get("openId");//付款人openId
        String frontUrl = param.get("frontUrl");//付款人openId
        if("2".equals(orderSource)){
            String key = MD5.encode(orgId + openId);
            String h5User = stringRedisTemplate.opsForValue().get("login:" + key);
            if(!StringUtils.isEmpty(h5User)){
                WxUser wxUser = JSON.parseObject(h5User, WxUser.class);
                openId = wxUser.getPayOpenId();
            }else{
                openId = wxShareDao.getPayOpenId(customerId);
            }
        }
        String distributor = param.get("distributor");//分享人
        String rebateStr = param.get("rebateStr");//活动反润比例
        String createCustomerId = param.get("createCustomerId");//创建人customerId
        String title = param.get("title");//活动名称（20字内）
        String enrollNotifyUrl = formUrl + "/h5/form/payCallback";//支付回调地址

        LOGGER.info("FormGetSignNew=================" + JSON.toJSONString(param));

        String s1 = stringRedisTemplate.opsForValue().get("enrollrecord:getsign_" + orderSn);
        if(!StringUtils.isEmpty(s1)){
            return (Map)JSON.parse(s1);
        }

        String[] strArr = {"recordPid", "distributor", "notifyUrl", "rebateStr"};
        for (Map.Entry<String, String> entry : param.entrySet()) {
            if(!Arrays.asList(strArr).contains(entry.getKey())){
                if (StringUtils.isEmpty(entry.getValue())) {
                    throw GlobalException.build("参数错误 " + entry.getKey());
                }
            }
        }

        Map<String, Object> resultMap;
        Map<String, Object> params = new HashMap<>();
        params.put("orgId", orgId);
        Integer payMode = mallDao.getPayModeByOrgId(params);
        if (payMode == null) {
            payMode = 1;
        }
        if (payMode == 1) {
            //微信支付
            Map<String, Object> wxPayParam = purchaseProcessService.getWxPayParam(openId, orderSn, totalFee, orgId, false);
            String url = wcPayProperties.getPayurl() + "/pay/wcpay";
            String result;
            try {
                LOGGER.info("getSign,wxPayParam===" + wxPayParam.toString());
                result = httpService.doPost(url, wxPayParam);
                LOGGER.info("getSign,result===" + result);
            } catch (URISyntaxException | IOException e) {
                LOGGER.error("支付网关调用异常");
                throw GlobalException.build("支付网关调用异常");
            }
            String s = purchaseProcessService.callResultProcessWx(result);
            resultMap = (Map) JSON.parse(s);
        } else {
            // 通联支付
            String s = this.tlPayDetail(Integer.valueOf(totalFee), orgId, rebateStr, customerId, distributor, orderSn, openId, orderSource, payMode, recordPid, createCustomerId, title, frontUrl);
            resultMap = (Map) JSON.parse(s);
        }
        resultMap.put("orderSn", orderSn);
        stringRedisTemplate.opsForValue().set("enrollrecord:getsign_"+orderSn,JSON.toJSONString(resultMap),1,TimeUnit.DAYS);
        stringRedisTemplate.opsForValue().set("enrollrecord:key_"+orderSn,JSON.toJSONString(param),365,TimeUnit.DAYS);
        stringRedisTemplate.opsForValue().set("enrollnotify:key_"+orderSn,enrollNotifyUrl,365,TimeUnit.DAYS);
        return resultMap;
    }

    private String tlPayDetail(Integer pay,String orgId,String rebateStr,String customerId,String distributor,String orderSn,String openid,String orderSource,Integer payMode,String recordPid,String createCustomerId,String title,String frontUrl) {
        Map<String, Integer> reverseProfitModel = mallBoomDao.getReverseProfitModel(orgId);
        Integer serviceRatio;// 商品服务费占比例,eg:50
        Integer recommendRatio;// 商品推荐费比例
        Integer unhappen;// 未产生费用给谁 1-商家2-机构
        if (reverseProfitModel == null) {
            // 机构没有设置返润模式
            serviceRatio = 50;
            recommendRatio = 50;
            unhappen = 1;
        } else {
            serviceRatio = reverseProfitModel.get("serviceRatio");
            recommendRatio = reverseProfitModel.get("recommendRatio");
            unhappen = reverseProfitModel.get("unhappen");
        }
        if (StringUtils.isEmpty(rebateStr)) {
            rebateStr = "0";
        }
        Double rebate = Double.valueOf(rebateStr);
        double i = rebate * serviceRatio.doubleValue() / 100;// 服务费比例,eg:10
        double j = rebate * recommendRatio.doubleValue() / 100;// 推荐费比例,eg:10
        double iv = pay.doubleValue() * i / 100;// 服务费
        double jv = pay.doubleValue() * j / 100;// 推荐费
        int sharePrice = new BigDecimal(iv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(服务费)1
        int recomPrice = new BigDecimal(jv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(推荐费)2
        double goodsAllRebate = pay.doubleValue() * rebate / 100;
        int totalPrice = new BigDecimal(goodsAllRebate).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 总返利值
        int platformPrice = totalPrice - sharePrice - recomPrice;// 返利值(平台费)3
        Map<String, String> platformRateMap = purchaseProcessDao.getPlatformRateByOrgId(orgId);
        // lh抽成
        Double linkerTake = Double.valueOf(platformRateMap.get("linkerTake"));
        // 大b抽成
        Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));

        double v2 = pay * linkerTake / 100;
        int linkerFee = new BigDecimal(v2).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        double v3 = pay * unionBarleyTake / 100;
        int unionBarleyFee = new BigDecimal(v3).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        // 平台费3
        int platformFee = linkerFee + unionBarleyFee;
        // 1-sharePrice-分享人（联汇子账户） 2-recomPrice-推荐人（联汇子账户）3-platformFee-联汇（联汇子账户） 4-income-商品拥有者（小b账户）
        // 1+2+3 先打到联汇账户，多出来的打给小b账户，然后联汇打积分抵扣的金额给小b账户
        int lh = totalPrice + platformFee;
        if (pay < lh) {
            throw GlobalException.build("用户支付金额不足");
        }

        // 上级id
        String pid = purchaseProcessDao.getPidByCid(customerId);
        if(StringUtils.isEmpty(pid)){
            if(!StringUtils.isEmpty(recordPid)){
                Map<String, Object> tmpParam = new HashMap<>();
                tmpParam.put("orgId", orgId);
                tmpParam.put("customerId", recordPid);
                Integer promoterCount = mallBoomDao.getPromoterCount(tmpParam);
                if (promoterCount > 0) {
                    pid = recordPid;
                }else{
                    pid = "";
                }
            }else{
                pid = "";
            }
        }
        // 是否产出推荐费给推荐人
        boolean ifRf = !StringUtils.isEmpty(pid) && recomPrice != 0 && !pid.equals(customerId);

        if (!StringUtils.isEmpty(pid)) {
            // 推广员不返推荐费
            Map<String, Long> role = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
            Long a = role.get("a");
            Long b = role.get("b");
            Long c = role.get("c");
            if (a == 0 && b == 1 && c == 0) {
                ifRf = false;
            }
        }
        // 是否产出服务费给分享人
        boolean ifFw = !StringUtils.isEmpty(distributor) && sharePrice != 0 && !distributor.equals(customerId);

        // 分享人是否是普通用户(是普通用户只分金币)
        boolean distributorIsNormal = false;
        if (ifFw) {
            distributorIsNormal = purchaseProcessService.getUserRole(distributor);
        }

        // 根据配置读取 服务费、推荐费、联汇抽成、大b抽成分别给谁
        List<AccountInfo> subAccountList = new ArrayList<>();
        Map<String, Integer> subAccountMap = new HashMap<>();
        if (ifRf) {
            subAccountMap.put(FeeConstants.RECOMMEND_FEE, recomPrice);
        } else {
            if (unhappen == 1) {
                lh -= recomPrice;
            } else {
                platformPrice += recomPrice;
            }
        }
        if (ifFw) {
            subAccountMap.put(distributorIsNormal ? FeeConstants.SERVICE_COIN_FEE : FeeConstants.SERVICE_FEE, sharePrice);
        } else {
            if (unhappen == 1) {
                lh -= sharePrice;
            } else {
                platformPrice += sharePrice;
            }
        }
        subAccountMap.put(FeeConstants.LINK_DRAW_FEE, linkerFee);
        subAccountMap.put(FeeConstants.ORG_DRAW_FEE, unionBarleyFee + platformPrice);
        for (String s : subAccountMap.keySet()) {
            subAccountList.add(purchaseProcessService.getAccountMap(s, subAccountMap.get(s), orgId, payMode));
        }
        Map<String, Integer> collect = subAccountList.stream()
                .collect(Collectors.groupingBy(AccountInfo::getCustomerId, Collectors.summingInt(AccountInfo::getAmount)));

        String orgUid = purchaseProcessDao.getAccountUidByOrgId(orgId);
        // 每个机构一个联汇子账号
        String linkId = "";
        if(payMode==2){
            linkId =purchaseProcessDao.getLinkIdByOrgId(orgId);
        }else if(payMode==3){
            linkId = purchaseProcessDao.getLinkIdByLinkOrg("linker");
        }
        if (StringUtils.isEmpty(linkId)) {
            throw GlobalException.build("联汇子账号暂未绑定");
        }
        // 请求参数
        Map<String, Object> reqMap = new HashMap<>();
        // 现金支付金额
        reqMap.put("cashAmount", pay);

        boolean toOrg = createCustomerId.equals(orgId);
        String belongUid = "";
        if (!toOrg) {
            belongUid = purchaseProcessDao.getAccountUidByCustomerId(createCustomerId);
        }

        List<Map<String, Object>> cashSplitItems = new ArrayList<>();
        if (pay != lh) {
            // 用户钱一部分到大b
            Map<String, Object> cashSplitItem1 = new HashMap<>();
            cashSplitItem1.put("customerId", toOrg ? orgUid : belongUid);
            cashSplitItem1.put("splitAmount", pay - lh);
            if(toOrg){
                cashSplitItem1.put("type", 1);
            }else {
                cashSplitItem1.put("type", 0);
            }
            cashSplitItem1.put("note", "表单收益");
            cashSplitItem1.put("orderId", orderSn);
            cashSplitItems.add(cashSplitItem1);
        }
        // 用户钱到lh
        // 余额支出账户(现金分入账户，推荐费，服务费，大b抽成，联汇抽成)
        String feeId = purchaseProcessService.getCustomerIdByFeeTypeAndOrdId(FeeConstants.SERVICE_FEE, orgId, payMode);

        String feeCustomerId = purchaseProcessDao.getCustomerAccountNumberByCustomerId(feeId);

        collect.forEach((x, y) -> {
            if (y == 0) {
                return;
            }
            Map<String, Object> cashSplitItem = new HashMap<>();
            cashSplitItem.put("customerId", x);
            cashSplitItem.put("splitAmount", y);
            cashSplitItem.put("note", "表单收益-平台费");
            if(orgUid.equals(x)){
                cashSplitItem.put("type", 1);
            }else {
                cashSplitItem.put("type", 0);
            }
            cashSplitItem.put("orderId", orderSn);
            cashSplitItems.add(cashSplitItem);
        });
        // 现金分账明细，JSON字符串
        if (cashSplitItems.size() > 0) {
            reqMap.put("cashSplitItems", JSON.toJSONString(cashSplitItems));
        }
        // 收款人id 收款人银行账号 金额 备注 订单sn
        // [{"customerId":"C20190906Bgw72a","customerAccountNumber":"","splitAmount":"10000","note":"商品收益","orderId":"100001"}]
        // 支付用户ID
        reqMap.put("customerId", customerId);
        // 商品描述
        reqMap.put("goodsName", title);
        // 支付用户OPENID
        reqMap.put("openID", openid);
        // 平台订单ID
        reqMap.put("orderSn", orderSn);
        // 收款用户帐号(收款用户为机构会员时必填，机构结算标识)(大b账号)
//        reqMap.put("payeeAccountNumber", orgAccountNumber);
        // 收款用户ID
        reqMap.put("payeeUserID", orgUid);
        // 余额支出账户
        reqMap.put("feeCustomerId", feeCustomerId);
        //支付后跳转地址
        reqMap.put("frontUrl", frontUrl);

        // 获取用户是否app 的
        String appId = "";
        String payType = "";
        if("2".equals(orderSource)){
            // 小程序appId
            appId = purchaseProcessDao.getXcxAppIdByOrgId(orgId);
            payType = "XCX";
        }else{
            // 应用appId
            if(payMode == 3){
                appId = purchaseProcessDao.getAppIdByOrgId("linker");
                payType = "WX";
            }
            if(payMode == 2){
                appId = purchaseProcessDao.getAppIdByOrgId(orgId);
                payType = "WX";
            }
        }
        if (StringUtils.isEmpty(appId)) {
            throw GlobalException.build("appId获取失败");
        }
        reqMap.put("appId", appId);
        // 行业代码
        String industryCode = purchaseProcessDao.getOrgMerchantInfoByOrgId(orgId);
        reqMap.put("industryCode", industryCode);
        // 行业名称
        String industryName = purchaseProcessDao.getIndustryNameByCode(industryCode);
        reqMap.put("industryName", industryName);
        // 支付方式：WX-公众号支付；XCX-微信小程序支付
        reqMap.put("payType", payType);
        // 访问终端类型:1手机；2PC
        reqMap.put("source", 1);
        // 交易验证方式：0-无验证；1-短信验证码；2-支付密码
        reqMap.put("validateType", 0);
        //回调地址
//        reqMap.put("notifyUrl", formUrl + "/h5/form/payCallback");
        // 测试环境用yt
        String alias = "";
        if(payMode == 3){
            alias = maiBaoLaService.getAliasByLinker();
        }
        if(payMode == 2){
            alias = maiBaoLaService.getAlias(orgId);
        }
        reqMap.put("clintType", alias);
        // 手续费
        reqMap.put("fee", 0);
        String url = wcPayProperties.getAcsurl() + WcPayConstant.TRADE_PAY_ORDER;
        // 请求支付网关
        String result = "";
        try {
            LOGGER.info("request__TL===" + JSON.toJSONString(reqMap));
            result = httpService.doPost(url, JSON.toJSONString(reqMap), WcPayConstant.JSON);
            result = purchaseProcessService.callResultProcess(result);
        } catch (Exception e) {
            LOGGER.error("支付网关调用异常", e);
            throw GlobalException.build("支付网关调用异常");
        }
        return result;
    }




    public Map<String, Object> getInfo(Map<String, Object> param) {
        Map<String, Object> info = enrollActiveDao.getInfo(param);

        if (null != info) {
            if ("1".equals(info.get("isSeal").toString()) || "2".equals(info.get("status").toString())) {
                //报名被删掉或被封禁，如果是小b创建的活动，404返回创建人cid
                String cid = (String) info.get("customerId");
                String orgId = (String) info.get("orgId");
                if (!cid.equals(orgId)) {
                    throw GlobalException.notFound(cid);
                } else {
                    throw GlobalException.notFound();
                }
            }
        } else {
            throw GlobalException.notFound();
        }

        List<Map<String, Object>> option = enrollActiveDao.getOption(param.get("enrollId").toString());
        for (Map<String, Object> o : option) {
            if (!StringUtils.isEmpty(o.get("optionPrice"))) {
                o.put("optionPrice", NumberUtils.fenToYuan(Long.valueOf(o.get("optionPrice").toString())));
            }
        }
        info.put("options", option);
        info.put("attributes", enrollActiveDao.getAttribute(param.get("enrollId").toString()));
        return info;
    }


    public List<Map<String, Object>> getMyEnrollList(Map<String, String> param) {
        return enrollActiveDao.getMyEnrollList(param);
    }

    public int getCustomerRecordCount(Map<String, Object> param) {
        return enrollActiveDao.getCustomerRecordCount(param);
    }

    public Map<String,Object> getMyCustomerRecord(Map<String, Object> param) {
        return enrollActiveDao.getCustomerRecord(param);
    }

    public List<Map<String, Object>> getAttribute(String enrollId) {
        return enrollActiveDao.getAttribute(enrollId);
    }

    public Map addRecord(Map<String, Object> param, boolean isEdit) {
        String customerId = param.get("customerId").toString();
        String enrollId = param.get("enrollId").toString();
        Map<String, Object> info = enrollActiveDao.getInfo(param);
        //若不是编辑的时候调用，不判断活动时间和状态
        if (!isEdit) {
            if ("0".equals(info.get("status"))) {
                throw GlobalException.build("活动暂未开启");
            }
            if ("2".equals(info.get("status"))) {
                throw GlobalException.build("活动已取消");
            }
            LocalDateTime now = LocalDateTime.now();
            if (!StringUtils.isEmpty(info.get("startTime"))) {
                Timestamp startTime = (Timestamp) info.get("startTime");
                LocalDateTime startDateTime = startTime.toLocalDateTime();
                if (now.isBefore(startDateTime)) {
                    throw GlobalException.build("活动还未开始");
                }
            }
            if (!StringUtils.isEmpty(info.get("endTime"))) {
                Timestamp endTime = (Timestamp) info.get("endTime");
                LocalDateTime endDateTime = endTime.toLocalDateTime();
                if (now.isAfter(endDateTime)) {
                    throw GlobalException.build("活动已结束");
                }
            }
        }

        String optionId = (String) param.get("optionId");

        String key = ENROLL_KEY + optionId;
        String lock = stringRedisTemplate.opsForList().rightPop(key);
        if (StringUtils.isEmpty(lock)) {
            throw GlobalException.build("当前报名项人数已满");
        }

        Map<String, Object> optionInfo = enrollActiveDao.getOptionByOptionId(optionId);
        Integer maxNum = (Integer) optionInfo.get("maxNum");
        Integer existNum = (Integer) optionInfo.get("existNum");
        String optionName = (String) optionInfo.get("optionName");
        String orderSn = TransactionOrderUtil.TYPE_ENROLL + TransactionOrderUtil.getPrimaryKey();
        if (maxNum > 0) {
            //有最大报名人数限制
            if (existNum > maxNum || existNum.equals(maxNum)) {
                throw GlobalException.build("【" + optionName + "】报名人数已满");
            }
        }

        String needpay = (String) info.get("needpay");
        Integer optionPrice = (Integer) optionInfo.get("optionPrice");
        if ("1".equals(needpay)) {
            //需要在线支付
            if (optionPrice > 0) {
                //报名金额大于0
                param.put("orderSn", orderSn);
                param.put("payAmount", optionPrice);
                param.put("payStatus", "0");
            } else {
                //报名金额为0
                param.put("payStatus", "1");
                param.put("payTime", "1");
            }
        } else {
            //不需要在线支付
            param.put("payStatus", "1");
            param.put("payTime", "1");
        }
        param.put("id",0);
        enrollActiveDao.addRecord(param);//保存表单记录
        Integer recordId =(Integer) param.get("id");
        this.addExistNum(param);//增加已报名人数
        if ("1".equals(info.get("isRepeat").toString())) {
            String s = stringRedisTemplate.opsForValue().get("enroll:enroll_overview_guestnum" + enrollId + customerId);
            if (StringUtils.isEmpty(s)) {
                overViewInfoService.insertOrUpdateEnroll("GUEST_NUM", param.get("enrollId").toString(), 1, false);
            } else {
                stringRedisTemplate.delete("enroll:enroll_overview_guestnum" + enrollId + customerId);
            }
        }
        Map<String, Object> res = new HashMap<>();
        res.put("id", recordId);
        res.put("ifSuccess", "1");
        String payStatus = (String) param.get("payStatus");
        if ("0".equals(payStatus)) {
            res.put("needToPay", "1");
            // 判断是否app
            if ("1".equals(param.get("orderSource").toString())) {
                Map<String, Object> customerRecord = enrollActiveDao.getCustomerRecordMap(param);
                //            this.checkEnrollOrder(param);
                String frontUrl = "";
                if (!StringUtils.isEmpty(param.get("frontUrl"))) {
                    frontUrl = URLDecoder.decode(param.get("frontUrl").toString()) + "&recordId=" + recordId;
                }
                res.put("sign", this.getSign(customerRecord.get("customerId").toString(), orderSn, customerRecord.get("payAmountCent").toString(), customerRecord.get("orgId").toString(), customerRecord.get("enrollId").toString(), customerRecord.get("pid").toString(), param.get("openId").toString(), param.get("id").toString(), frontUrl));
            } else {
                res.put("orderSn", orderSn);
            }
        } else {
            res.put("needToPay", "0");
            res.put("sign", new HashMap<>());
            String orgId = param.get("orgId").toString();
            overViewInfoService.goodsData(null, enrollId, 3, null, null,
                    null, 1, optionPrice, customerId, orgId, null);
        }
        //打标签
        this.addEnrollLabel(customerId, enrollId);
        return res;
    }

    public Map updateRecord(Map<String, Object> param, Integer toPay) {
        Map<String, Object> info = enrollActiveDao.getInfo(param);
//        if ("2".equals(info.get("status"))) {
//            throw GlobalException.build("活动已取消");
//        }
        if ("1".equals(info.get("canedit")) || 1 == toPay) {
            Map<String, Object> customerRecord = enrollActiveDao.getCustomerRecordMap(param);
            if (null == customerRecord) {
                throw GlobalException.build("参数错误");
            }
            if (StringUtils.isEmpty(param.get("pid"))) {
                param.put("pid", customerRecord.get("pid"));
            }
            String oldOptionId = (String) param.get("oldOptionId");
            String optionId = (String) param.get("optionId");
            //若换了报名项，删除原报名记录，新增新记录；防并发队列增加元素
            if (!oldOptionId.equals(optionId)) {
                Map<String, Object> cutNum = new HashMap<>(param);
                cutNum.put("optionId", oldOptionId);
                this.cutExistNum(cutNum);
                enrollActiveDao.delRecrodByEnrollIdAndCustomerId(param);
                String key = ENROLL_KEY + oldOptionId;
                stringRedisTemplate.opsForList().leftPush(key, "1");
                return this.addRecord(param, true);
            }

            String orderSn = TransactionOrderUtil.TYPE_ENROLL + TransactionOrderUtil.getPrimaryKey();
            if ("0".equals(customerRecord.get("payStatus"))) {
                param.put("orderSn", orderSn);
            }
            enrollActiveDao.updateRecord(param);

            Map<String, Object> res = new HashMap<>();
            res.put("ifSuccess", "1");
            res.put("id", param.get("id"));
            if ("0".equals(customerRecord.get("payStatus"))) {
                res.put("needToPay", "1");
                if ("1".equals(param.get("orderSource").toString())) {
//                this.checkEnrollOrder(param);
                    String frontUrl = "";
                    if (!StringUtils.isEmpty(param.get("frontUrl"))) {
                        frontUrl = URLDecoder.decode(param.get("frontUrl").toString()) + "&recordId=" + param.get("id");
                    }
                    res.put("sign", this.getSign(customerRecord.get("customerId").toString(), orderSn, customerRecord.get("payAmountCent").toString(), customerRecord.get("orgId").toString(), customerRecord.get("enrollId").toString(), customerRecord.get("pid").toString(), param.get("openId").toString(), param.get("id").toString(), frontUrl));
                } else {
                    res.put("orderSn", orderSn);
                }
            } else {
                res.put("needToPay", "0");
                res.put("sign", new HashMap<>());
            }
            return res;
        } else {
            throw GlobalException.build("该活动不允许修改报名信息");
        }
    }

    //打标签
    private void addEnrollLabel(String customerId,String enrollId){
        List<String> labelIds = enrollActiveDao.getEnrollLabelIdList(enrollId);
        for(String labelId:labelIds){
            Map<String,Object> param = new HashMap<>(2);
            param.put("labelId",labelId);
            param.put("customerId",customerId);
            enrollActiveDao.addEnrollLabel(param);
        }
    }

    /**
     * 检测必填项是否填写完整
     *
     * @param param
     */
    public void getRecordAttr(Map<String, Object> param) {
        String enrollId = (String) param.get("enrollId");
        List<String> needAttrIdByEnrollId = enrollActiveDao.getNeedAttrIdByEnrollId(enrollId);
        List<Map<String, Object>> record = (List<Map<String, Object>>) param.get("record");
        if (null == record || record.size() == 0) {
            throw GlobalException.build("参数错误");
        }
        List<String> attrIds = new ArrayList<>();
        for (Map<String, Object> da : record) {
            String attrId = (String) da.get("attrId");
            attrIds.add(attrId);
            boolean contains = needAttrIdByEnrollId.contains(attrId);
            if (contains && StringUtils.isEmpty(da.get("attrValue"))) {
                throw GlobalException.build("请填写完整");
            }
        }
        boolean need = attrIds.containsAll(needAttrIdByEnrollId);
        if (!need) {
            throw GlobalException.build("请填写完整");
        }
    }

    public Map<String, Object> getOptionByOptionId(String optionId) {
        Map<String, Object> optionByOption = enrollActiveDao.getOptionByOptionId(optionId);
        optionByOption.put("optionPrice", NumberUtils.fenToYuan(Long.valueOf(optionByOption.get("optionPrice").toString())));
        return optionByOption;
    }

    public Map<String, Object> getEnrollBase(Map<String, Object> param) {
        Map<String, Object> info = enrollActiveDao.getInfo(param);

        if (null != info) {
            if ("1".equals(info.get("isSeal").toString()) || "2".equals(info.get("status").toString())) {
                //报名被删掉或被封禁，如果是小b创建的活动，404返回创建人cid
                String cid = (String) info.get("customerId");
                String orgId = (String) info.get("orgId");
                if (!cid.equals(orgId)) {
                    throw GlobalException.notFound(cid);
                } else {
                    throw GlobalException.notFound();
                }
            }
        } else {
            throw GlobalException.notFound();
        }

        return info;
    }

    //增加报名人数
    public void addExistNum(Map<String, Object> param) {
        enrollActiveDao.addExistNum(param);
    }

    //减少报名人数
    public void cutExistNum(Map<String, Object> param) {
        enrollActiveDao.cutExistNum(param);
    }

    /**
     * 检查报名支付状态
     *
     * @param param
     */
//    private void checkEnrollOrder(Map<String, Object> param) {
//        ScheduledExecutorService scheduledExecutorService = new ScheduledThreadPoolExecutor(1);
//        scheduledExecutorService.schedule(() -> {
//            String optionId = (String) param.get("optionId");
//            String orderSn = (String) param.get("orderSn");
//            Map<String, Object> recordByOrderSn = enrollActiveDao.getRecordByOrderSn(orderSn);
//            if (null != recordByOrderSn) {
//                String payStatus = (String) recordByOrderSn.get("payStatus");
//                if ("0".equals(payStatus)) {
//                    //60分钟还没支付，名额回滚，报名人数减去，redis list加回名额，删除订单
//                    String key = ENROLL_KEY + optionId;
//                    stringRedisTemplate.opsForList().leftPush(key, "1");
//                    enrollActiveDao.cutExistNum(param);
//                    enrollActiveDao.delRecrod(orderSn);
//                }
//            }
//        }, 1, TimeUnit.HOURS);
//    }


    /**
     * 报名支付后完成订单
     * tradeSn 交易流水号
     * orderSn 订单编号
     *
     * @param param
     */
    public void finishRecord(Map<String, Object> param) {
        enrollActiveDao.finishRecord(param);
    }

    // TODO 获取签名(分微信支付和通联支付)
    private Map<String, Object> getSign(String customerId, String orderSn, String totalFee, String orgId, String enrollId, String distributor, String openId,String id,String frontUrl) {
//        String openId = purchaseProcessDao.getOpenIdByCustomerId(customerId);

        Map<String, Object> params = new HashMap<>();
        params.put("orgId", orgId);
        Integer payMode = mallDao.getPayModeByOrgId(params);
        if (payMode == null) {
            payMode = 1;
        }
        if (payMode == 1) {
            //微信支付
            Map<String, Object> wxPayParam = purchaseProcessService.getWxPayParam(openId, orderSn, totalFee, orgId, false);
            String url = wcPayProperties.getPayurl() + "/pay/wcpay";
            String result;
            try {
                LOGGER.info("getSign,wxPayParam===" + wxPayParam.toString());
                result = httpService.doPost(url, wxPayParam);
                LOGGER.info("getSign,result===" + result);
            } catch (URISyntaxException | IOException e) {
                LOGGER.error("支付网关调用异常");
                throw GlobalException.build("支付网关调用异常");
            }
            String s = purchaseProcessService.callResultProcessWx(result);
            Map resultMap = (Map) JSON.parse(s);
            // noinspection unchecked
            resultMap.put("orderSn", orderSn);
            return resultMap;
        } else {
            // 通联支付
            String s = this.tlPay(Integer.valueOf(totalFee), orgId, enrollId, customerId, distributor, orderSn, openId,1,payMode,id,frontUrl);
            Map resultMap = (Map) JSON.parse(s);
            // noinspection unchecked
            resultMap.put("orderSn", orderSn);
            return resultMap;
        }
    }

    private String tlPay(Integer pay, String orgId, String enrollId, String customerId, String distributor, String orderSn, String openid, Integer orderSource, Integer payMode,String id,String frontUrl) {
        Map<String, Integer> reverseProfitModel = mallBoomDao.getReverseProfitModel(orgId);
        Integer serviceRatio;// 商品服务费占比例,eg:50
        Integer recommendRatio;// 商品推荐费比例
        Integer unhappen;// 未产生费用给谁 1-商家2-机构
        if (reverseProfitModel == null) {
            // 机构没有设置返润模式
            serviceRatio = 50;
            recommendRatio = 50;
            unhappen = 1;
        } else {
            serviceRatio = reverseProfitModel.get("serviceRatio");
            recommendRatio = reverseProfitModel.get("recommendRatio");
            unhappen = reverseProfitModel.get("unhappen");
        }
        String rebateStr = enrollActiveDao.getRebateByEnrollId(enrollId);
        if (StringUtils.isEmpty(rebateStr)) {
            rebateStr = "0";
        }
        Double rebate = Double.valueOf(rebateStr);
        double i = rebate * serviceRatio.doubleValue() / 100;// 服务费比例,eg:10
        double j = rebate * recommendRatio.doubleValue() / 100;// 推荐费比例,eg:10
        double iv = pay.doubleValue() * i / 100;// 服务费
        double jv = pay.doubleValue() * j / 100;// 推荐费
        int sharePrice = new BigDecimal(iv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(服务费)1
        int recomPrice = new BigDecimal(jv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(推荐费)2
        double goodsAllRebate = pay.doubleValue() * rebate / 100;
        int totalPrice = new BigDecimal(goodsAllRebate).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 总返利值
        int platformPrice = totalPrice - sharePrice - recomPrice;// 返利值(平台费)3
        Map<String, String> platformRateMap = purchaseProcessDao.getPlatformRateByOrgId(orgId);
        // lh抽成
        Double linkerTake = Double.valueOf(platformRateMap.get("linkerTake"));

        // 大b抽成
        Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));

        // 平台总抽成
        Double platformRate = linkerTake + unionBarleyTake;


        double v2 = pay * linkerTake / 100;
        int linkerFee = new BigDecimal(v2).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        double v3 = pay * unionBarleyTake / 100;
        int unionBarleyFee = new BigDecimal(v3).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        // 平台费3
        int platformFee = linkerFee + unionBarleyFee;
        // 商品收益=订单总金额-推荐费-服务费-平台费4
        int income = pay - totalPrice - platformFee;
        // 1-sharePrice-分享人（联汇子账户） 2-recomPrice-推荐人（联汇子账户）3-platformFee-联汇（联汇子账户） 4-income-商品拥有者（小b账户）
        // 1+2+3 先打到联汇账户，多出来的打给小b账户，然后联汇打积分抵扣的金额给小b账户
        int lh = totalPrice + platformFee;
        if (pay < lh) {
            throw GlobalException.build("用户支付金额不足");
        }

        // 上级id
        String pid = purchaseProcessDao.getPidByCid(customerId);
        if(StringUtils.isEmpty(pid)){
            Map<String,Object> recParam = new HashMap<>(1);
            recParam.put("id",id);
            Map<String, Object> customerRecord = enrollActiveDao.getCustomerRecordMap(recParam);
            if(!StringUtils.isEmpty(customerRecord.get("pid"))){
                String tmpPid = customerRecord.get("pid").toString();
                Map<String, Object> tmpParam = new HashMap<>();
                tmpParam.put("orgId", orgId);
                tmpParam.put("customerId", tmpPid);
                Integer promoterCount = mallBoomDao.getPromoterCount(tmpParam);
                if (promoterCount > 0) {
                    pid = tmpPid;
                }else{
                    pid = "";
                }
            }else{
                pid = "";
            }
        }
        // 是否产出推荐费给推荐人
        boolean ifRf = !StringUtils.isEmpty(pid) && recomPrice != 0 && !pid.equals(customerId);

        if (!StringUtils.isEmpty(pid)) {
            // 推广员不返推荐费
            Map<String, Long> role = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
            Long a = role.get("a");
            Long b = role.get("b");
            Long c = role.get("c");
            if (a == 0 && b == 1 && c == 0) {
                ifRf = false;
            }
        }
        // 是否产出服务费给分享人
        boolean ifFw = !StringUtils.isEmpty(distributor) && sharePrice != 0 && !distributor.equals(customerId);

        // 分享人是否是普通用户(是普通用户只分金币)
        boolean distributorIsNormal = false;
        if (ifFw) {
            distributorIsNormal = purchaseProcessService.getUserRole(distributor);
        }

        // 根据配置读取 服务费、推荐费、联汇抽成、大b抽成分别给谁
        List<AccountInfo> subAccountList = new ArrayList<>();
        Map<String, Integer> subAccountMap = new HashMap<>();
        if (ifRf) {
            subAccountMap.put(FeeConstants.RECOMMEND_FEE, recomPrice);
        } else {
            if (unhappen == 1) {
                lh -= recomPrice;
            } else {
                platformPrice += recomPrice;
            }
        }
        if (ifFw) {
            subAccountMap.put(distributorIsNormal ? FeeConstants.SERVICE_COIN_FEE : FeeConstants.SERVICE_FEE, sharePrice);
        } else {
            if (unhappen == 1) {
                lh -= sharePrice;
            } else {
                platformPrice += sharePrice;
            }
        }
        subAccountMap.put(FeeConstants.LINK_DRAW_FEE, linkerFee);
        subAccountMap.put(FeeConstants.ORG_DRAW_FEE, unionBarleyFee + platformPrice);
        for (String s : subAccountMap.keySet()) {
            subAccountList.add(purchaseProcessService.getAccountMap(s, subAccountMap.get(s), orgId, payMode));
        }
        Map<String, Integer> collect = subAccountList.stream()
                .collect(Collectors.groupingBy(AccountInfo::getCustomerId, Collectors.summingInt(AccountInfo::getAmount)));

        String orgUid = purchaseProcessDao.getAccountUidByOrgId(orgId);
        // 每个机构一个联汇子账号
        String linkId = "";
        if(payMode==2){
            linkId =purchaseProcessDao.getLinkIdByOrgId(orgId);
        }else if(payMode==3){
            linkId = purchaseProcessDao.getLinkIdByLinkOrg("linker");
        }
        if (StringUtils.isEmpty(linkId)) {
            throw GlobalException.build("联汇子账号暂未绑定");
        }
        // 请求参数
        Map<String, Object> reqMap = new HashMap<>();
        // 现金支付金额
        reqMap.put("cashAmount", pay);

        Map<String, Object> enrollIdAndOrgId = new HashMap<>();
        enrollIdAndOrgId.put("orgId", orgId);
        enrollIdAndOrgId.put("enrollId", enrollId);
        Map<String, Object> info = enrollActiveDao.getInfo(enrollIdAndOrgId);
        String toCustomerId = (String) info.get("customerId");
        boolean toOrg = toCustomerId.equals(orgId);
        String belongUid = "";
        if (!toOrg) {
            belongUid = purchaseProcessDao.getAccountUidByCustomerId(toCustomerId);
        }

        List<Map<String, Object>> cashSplitItems = new ArrayList<>();
        if (pay != lh) {
            // 用户钱一部分到大b
            Map<String, Object> cashSplitItem1 = new HashMap<>();
            cashSplitItem1.put("customerId", toOrg ? orgUid : belongUid);
            cashSplitItem1.put("splitAmount", pay - lh);
            if(toOrg){
                cashSplitItem1.put("type", 1);
            }else {
                cashSplitItem1.put("type", 0);
            }
            cashSplitItem1.put("note", "商品收益");
            cashSplitItem1.put("orderId", orderSn);
            cashSplitItems.add(cashSplitItem1);
        }
        // 用户钱到lh
        // 余额支出账户(现金分入账户，推荐费，服务费，大b抽成，联汇抽成)
        String feeId = purchaseProcessService.getCustomerIdByFeeTypeAndOrdId(FeeConstants.SERVICE_FEE, orgId, payMode);

        String feeCustomerId = purchaseProcessDao.getCustomerAccountNumberByCustomerId(feeId);

        collect.forEach((x, y) -> {
            if (y == 0) {
                return;
            }
            Map<String, Object> cashSplitItem = new HashMap<>();
            cashSplitItem.put("customerId", x);
            cashSplitItem.put("splitAmount", y);
            cashSplitItem.put("note", "商品收益-平台费");
            if(orgUid.equals(x)){
                cashSplitItem.put("type", 1);
            }else {
                cashSplitItem.put("type", 0);
            }
            cashSplitItem.put("orderId", orderSn);
            cashSplitItems.add(cashSplitItem);
        });
        // 现金分账明细，JSON字符串
        if (cashSplitItems.size() > 0) {
            reqMap.put("cashSplitItems", JSON.toJSONString(cashSplitItems));
        }
        // 收款人id 收款人银行账号 金额 备注 订单sn
        // [{"customerId":"C20190906Bgw72a","customerAccountNumber":"","splitAmount":"10000","note":"商品收益","orderId":"100001"}]
        reqMap.put("frontUrl", frontUrl);//支付后跳转前端地址
        // 支付用户ID
        reqMap.put("customerId", customerId);
        // 商品描述
        String goodsName = (String) info.get("title");
        reqMap.put("goodsName", goodsName);
        // 支付用户OPENID
        reqMap.put("openID", openid);
        // 平台订单ID
        reqMap.put("orderSn", orderSn);
        // 收款用户帐号(收款用户为机构会员时必填，机构结算标识)(大b账号)
//        reqMap.put("payeeAccountNumber", orgAccountNumber);
        // 收款用户ID
        reqMap.put("payeeUserID", orgUid);
        // 余额支出账户
        reqMap.put("feeCustomerId", feeCustomerId);

        // 获取用户是否app 的
        String appId = "";
        String payType = "";
        if(orderSource==2){
            // 小程序appId
            appId = purchaseProcessDao.getXcxAppIdByOrgId(orgId);
            payType = "XCX";
        }else{
            // 应用appId
            if(payMode == 3){
                appId = purchaseProcessDao.getAppIdByOrgId("linker");
                payType = "WX";
            }
            if(payMode == 2){
                appId = purchaseProcessDao.getAppIdByOrgId(orgId);
                payType = "WX";
            }
        }
        if (StringUtils.isEmpty(appId)) {
            throw GlobalException.build("appId获取失败");
        }
        reqMap.put("appId", appId);
        // 行业代码
        String industryCode = purchaseProcessDao.getOrgMerchantInfoByOrgId(orgId);
        reqMap.put("industryCode", industryCode);
        // 行业名称
        String industryName = purchaseProcessDao.getIndustryNameByCode(industryCode);
        reqMap.put("industryName", industryName);
        // 支付方式：WX-公众号支付；XCX-微信小程序支付
        reqMap.put("payType", payType);
        // 访问终端类型:1手机；2PC
        reqMap.put("source", 1);
        // 交易验证方式：0-无验证；1-短信验证码；2-支付密码
        reqMap.put("validateType", 0);
        // 测试环境用yt
        String alias = "";
        if(payMode == 3){
            alias = maiBaoLaService.getAliasByLinker();
        }
        if(payMode == 2){
            alias = maiBaoLaService.getAlias(orgId);
        }
        reqMap.put("clintType", alias);
        // 手续费
        reqMap.put("fee", 0);
        String url = wcPayProperties.getAcsurl() + WcPayConstant.TRADE_PAY_ORDER;
        // 请求支付网关
        String result = "";
        try {
            LOGGER.info("request__TL===" + JSON.toJSONString(reqMap));
            result = httpService.doPost(url, JSON.toJSONString(reqMap), WcPayConstant.JSON);
            result = purchaseProcessService.callResultProcess(result);
        } catch (Exception e) {
            LOGGER.error("支付网关调用异常", e);
            throw GlobalException.build("支付网关调用异常");
        }
        return result;
    }

    // 报名支付回调
    public void enrollCallback(Map<String, Object> param) throws IOException, URISyntaxException {
        String totalFee = (String) param.get("totalFee");
        String orderSn = (String) param.get("orderSn");
        String tradeSn = (String) param.get("txsn");

        String enrollNotifyUrl;
        if(param.containsKey("enrollNotifyUrl") && !StringUtils.isEmpty(param.get("enrollNotifyUrl"))){
            enrollNotifyUrl = param.get("enrollNotifyUrl").toString();
        }else{
            enrollNotifyUrl = stringRedisTemplate.opsForValue().get("enrollnotify:key_"+orderSn);
        }
        if(!StringUtils.isEmpty(enrollNotifyUrl)){
            param.put("enrollNotifyUrl",enrollNotifyUrl);
            Map<String,String> header = new HashMap<>();
            header.put("Content-Type", "application/json;charset=UTF-8");
            LOGGER.info("请求中台回调:"+JSON.toJSONString(param));
            String res = httpService.doPost(enrollNotifyUrl, JSON.toJSONString(param), header);
            LOGGER.info("enrollCallBack:"+res);
            Map resData = (Map)JSON.parse(res);
            if(StringUtils.isEmpty(res) || !"200".equals(resData.get("code").toString())){
                stringRedisTemplate.opsForList().leftPush("enrollNotifyRetryList",JSON.toJSONString(param));
            }else{
                String record = stringRedisTemplate.opsForValue().get("enrollrecord:key_"+orderSn);
                if(!StringUtils.isEmpty(record)){
                    Map<String, Object> recordParam = (Map<String,Object>)JSON.parse(record);
                    recordParam.put("tradeSn",tradeSn);
                    recordParam.put("payAmount",param.get("totalFee"));
                    /*************************************报名支付完成后绑定人物上下级关系************************************/
                    if (!StringUtils.isEmpty(recordParam.get("distributor")) && !"0".equals(recordParam.get("distributor").toString())) {
                        Map<String, Object> tmpParam = new HashMap<>();
                        tmpParam.put("orgId", recordParam.get("orgId"));
                        tmpParam.put("customerId", recordParam.get("distributor"));
                        Integer promoterCount = mallBoomDao.getPromoterCount(tmpParam);
                        if (promoterCount > 0) {
                            Map<String, Object> ret = new HashMap<>();
                            ret.put("pcustomerId", recordParam.get("distributor"));
                            ret.put("customerId", recordParam.get("customerId"));
                            ret.put("parentShareWay", "shopping");
                            int customerParentCount = mallBoomDao.getCustomerParentCount(ret);
                            if(0 == customerParentCount){
                                mallBoomDao.saveCustomerParent(ret);
                            }
                        }
                    }
                    /*************************************报名支付完成后绑定人物上下级关系************************************/
                    //更新用户最后活跃时间
                    wxShareDao.setCustomerLastInteraction((String) recordParam.get("customerId"));
                    // 记账
                    this.saveOrgMoneyNew(recordParam);
                    //回调完成 删除对应缓存
                    stringRedisTemplate.delete("enrollrecord:key_"+orderSn);
                    stringRedisTemplate.delete("enrollnotify:key_"+orderSn);
                }else{
                    LOGGER.error("enrollCallBack:报名记录缓存丢失");
                }
            }
            return;
        }else{
            LOGGER.info("enrollCallBack:进入原报名回调");
        }

        //TODO
        Map<String, Object> record = enrollActiveDao.getRecordByOrderSn(orderSn);
        if(null == record){
            LOGGER.error("record is null===" + JSON.toJSONString(orderSn));
            return;
        }
        if("1".equals(record.get("payStatus"))){
            throw GlobalException.build("已支付");
        }
        if (!totalFee.equals(record.get("payAmount").toString())) {
            throw GlobalException.build("支付金额不正确");
        }
        // 完成订单
        Map<String, Object> recordParam = new HashMap<>();
        recordParam.put("orderSn", orderSn);
        recordParam.put("tradeSn", tradeSn);
        LOGGER.info("finishRecord===" + JSON.toJSONString(recordParam));
        enrollActiveDao.finishRecord(recordParam);


        //计算赠送积分和成长值
//        try {
//            scoreActiveCacheService.cacheOrderNum(orderSn);
//            scoreActiveCacheService.setCache(record.get("orgId").toString(),orderSn,totalFee,null,record.get("customerId").toString());
//        }catch (Exception e){
//            LOGGER.error("计算赠送积分和成长值失败",e);
//        }

        /*************************************报名支付完成后绑定人物上下级关系************************************/
        if (!StringUtils.isEmpty(record.get("pid"))) {
            Map<String, Object> tmpParam = new HashMap<>();
            tmpParam.put("orgId", record.get("orgId"));
            tmpParam.put("customerId", record.get("pid"));
            Integer promoterCount = mallBoomDao.getPromoterCount(tmpParam);
            if (promoterCount > 0) {
                Map<String, Object> ret = new HashMap<>();
                ret.put("pcustomerId", record.get("pid"));
                ret.put("customerId", record.get("customerId"));
                ret.put("parentShareWay", "shopping");
                int customerParentCount = mallBoomDao.getCustomerParentCount(ret);
                if(0 == customerParentCount){
                    mallBoomDao.saveCustomerParent(ret);
                }
                mallBoomDao.saveCustomerParent(ret);
            }
        }
        /*************************************报名支付完成后绑定人物上下级关系************************************/
        record.put("tradeSn", tradeSn);
        record.put("orderSn", orderSn);

        //更新用户最后活跃时间
        wxShareDao.setCustomerLastInteraction((String) record.get("customerId"));
        // 记账
        this.saveOrgMoney(record);
    }

    private void saveOrgMoneyNew(Map<String, Object> record) {
        LOGGER.info("saveOrgMoneyNew===" + JSON.toJSONString(record));
        String orderSn = (String) record.get("orderSn");
        String tradeSn = (String) record.get("tradeSn");
        String distributor = (String) record.get("distributor");
        String orgId = (String) record.get("orgId");
        String enrollId = (String) record.get("formId");
        String customerId = (String) record.get("customerId");
        Integer payAmount = Integer.valueOf(record.get("payAmount").toString());
        String toCustomerId = (String) record.get("createCustomerId");
        String title = (String) record.get("title");
        overViewInfoService.goodsData(null, enrollId, 3, null, null,
                null, 1, payAmount, customerId, orgId,null);
        Map<String, Integer> reverseProfitModel = mallBoomDao.getReverseProfitModel(orgId);// 返润模式
        Integer serviceRatio;// 商品服务费占比例,eg:50
        Integer recommendRatio;// 商品推荐费比例
        Integer originalRatio;// 商品创作费比例
        Integer unhappen;// 未产生费用给谁 1-商家2-机构
        if (reverseProfitModel == null) {
            // 机构没有设置返润模式
            serviceRatio = 50;
            recommendRatio = 50;
            originalRatio = 0;
            unhappen = 1;
        } else {
            serviceRatio = reverseProfitModel.get("serviceRatio");
            recommendRatio = reverseProfitModel.get("recommendRatio");
            originalRatio = reverseProfitModel.get("originalRatio");
            unhappen = reverseProfitModel.get("unhappen");
        }
        String rebateStr = (String)record.get("rebateStr");
        if (StringUtils.isEmpty(rebateStr)) {
            rebateStr = "0";
        }
        Double rebate = Double.valueOf(rebateStr);
        if(!StringUtils.isEmpty(distributor)){
            //异步
            Map clueMap = new HashMap();
            clueMap.put("promoterId",distributor);
            clueMap.put("customerId",customerId);
            clueMap.put("actionType",12);
            clueMap.put("relevantId",enrollId);
            clueMap.put("relevantName",title);
            clueMap.put("amount",NumberUtils.fenToYuan(Long.parseLong(payAmount.toString())));
            clueMap.put("orderSn",orderSn);
            clueMap.put("type",2);
            clueMap.put("orgId",orgId);
            //增加销售线索
            promoterClueService.addClue(clueMap);
        }
        double i = rebate * serviceRatio.doubleValue() / 100;// 服务费比例,eg:10
        double j = rebate * recommendRatio.doubleValue() / 100;// 推荐费比例,eg:10
        double k = rebate * originalRatio.doubleValue() / 100;  // 创作费比例,eg:10
        double iv = payAmount.doubleValue() * i / 100;// 服务费
        double jv = payAmount.doubleValue() * j / 100;// 推荐费
        double kv =payAmount.doubleValue() * k / 100; // 创作费
        int sharePrice = new BigDecimal(iv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(服务费)1
        int recomPrice = new BigDecimal(jv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(推荐费)2
        int originalPrice = new BigDecimal(kv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();        // 返利值(创作费)3
        double goodsAllRebate = payAmount.doubleValue() * rebate / 100;// 总返利
        int totalPrice = new BigDecimal(goodsAllRebate).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 总返利值
        int platformPrice = totalPrice - sharePrice - recomPrice-originalPrice;// 返利值(平台费)3
        if (platformPrice < 0) {
            // 推荐费服务费创作费都进位，平台费为0，导致总返利减去推荐费和服务费结果为-1，需要调整费用
            platformPrice = 0;
            if(totalPrice - recomPrice- originalPrice>0){
                sharePrice= totalPrice - recomPrice- originalPrice;
            }else if(totalPrice - recomPrice>0){
                sharePrice = 0;
                recomPrice = totalPrice - recomPrice;
            }
        }
        Map<String, String> platformRateMap = purchaseProcessDao.getPlatformRateByOrgId(orgId);
        // lh抽成
        Double linkerTake = Double.valueOf(platformRateMap.get("linkerTake"));
        // 大b抽成
        Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));

        double v2 = payAmount * linkerTake / 100;
        int linkerFee = new BigDecimal(v2).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        double v3 = payAmount * unionBarleyTake / 100;
        int unionBarleyFee = new BigDecimal(v3).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        // 平台费3
        int platformFee = linkerFee + unionBarleyFee;


        String pid = purchaseProcessDao.getPidByCid(customerId);
        // 是否产出推荐费给推荐人
        boolean ifRf = !StringUtils.isEmpty(pid) && recomPrice != 0 && !pid.equals(customerId);
        if (!StringUtils.isEmpty(pid)) {
            // 推广员不返推荐费
            Map<String, Long> role = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
            Long a = role.get("a");
            Long b = role.get("b");
            Long c = role.get("c");
            if (a == 0 && b == 1 && c == 0) {
                ifRf = false;
            }
            if (c == 0) {
                ifRf = false;
            }
        }
        // 是否产出服务费给分享人
        boolean ifFw = !StringUtils.isEmpty(distributor) && sharePrice != 0 && !distributor.equals(customerId) && !"0".equals(distributor);

        boolean distributorIsNormal = false;
        if (ifFw) {
            distributorIsNormal = purchaseProcessService.getUserRole(distributor);
        }

        Integer unhappenFee = originalPrice;
        List<Map<String, Object>> tradeInfos = new ArrayList<>();
        if (ifFw && ifRf) {
            // 服务
            Map<String, Object> tradeInfo1 = new HashMap<>();
            tradeInfo1.put("from", customerId);
            tradeInfo1.put("to", distributor);
            tradeInfo1.put("amount", sharePrice);
            // 积分交易类型0-金币抵扣，1-商品服务费，2 -金币退回
            tradeInfo1.put("tradeType", distributorIsNormal ? 1 : 2);
            // 支付方式1-rmb，2-积分
            tradeInfo1.put("payType", distributorIsNormal ? 2 : 1);
            tradeInfo1.put("receiveRole", 5);
            tradeInfo1.put("accountType", "");
            tradeInfo1.put("receiveAccount", "");
            tradeInfos.add(tradeInfo1);
            // 推荐
            Map<String, Object> tradeInfo2 = new HashMap<>();
            tradeInfo2.put("from", customerId);
            tradeInfo2.put("to", pid);
            tradeInfo2.put("amount", recomPrice);
            // 交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费，5-开通联盟商家平台费，6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商城商品平台费，10-商城商品收益，11-提现手续费
            tradeInfo2.put("tradeType", 3);
            tradeInfo2.put("payType", 1);
            tradeInfo2.put("receiveRole", 5);
            tradeInfo2.put("accountType", "");
            tradeInfo2.put("receiveAccount", "");
            tradeInfos.add(tradeInfo2);
        } else if (ifFw) {
            // 仅服务费
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("to", distributor);
            tradeInfo.put("amount", sharePrice);
            tradeInfo.put("tradeType", distributorIsNormal ? 1 : 2);
            tradeInfo.put("payType", distributorIsNormal ? 2 : 1);
            tradeInfo.put("receiveRole", 5);
            tradeInfo.put("accountType", "");
            tradeInfo.put("receiveAccount", "");
            tradeInfos.add(tradeInfo);
            unhappenFee += recomPrice;

        } else if (ifRf) {
            // 仅推荐费
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("to", pid);
            tradeInfo.put("amount", recomPrice);
            tradeInfo.put("tradeType", 3);
            tradeInfo.put("payType", 1);
            tradeInfo.put("receiveRole", 5);
            tradeInfo.put("accountType", "");
            tradeInfo.put("receiveAccount", "");
            tradeInfos.add(tradeInfo);
            unhappenFee += sharePrice;
        } else {
            // 两笔钱都无人认领
            unhappenFee += recomPrice + sharePrice;
        }
//        Integer income = payAmount - totalPrice - platformFee;
        if (unhappen == 1) {
//            income += unhappenFee;
            totalPrice -= unhappenFee;
        } else if (unhappen == 2 && unhappenFee > 0) {
            // 未产生费用给平台
//            unionBarleyFee += unhappenFee;
            platformPrice += unhappenFee;
        }
//        unionBarleyFee += platformPrice;
        if (platformPrice != 0) {
            // 大b平台费
            Map<String, Object> tradeInfo1 = new HashMap<>();
            tradeInfo1.put("from", customerId);
            tradeInfo1.put("to", orgId);
//            tradeInfo1.put("amount", unionBarleyFee);
            tradeInfo1.put("amount", platformPrice);
            tradeInfo1.put("tradeType", 4);
            tradeInfo1.put("payType", 1);
            tradeInfo1.put("receiveRole", 1);
            tradeInfo1.put("accountType", "");
            tradeInfo1.put("receiveAccount", "");
            tradeInfos.add(tradeInfo1);
        }
        if (linkerFee != 0) {
            // 联汇平台费
            Map<String, Object> tradeInfo2 = new HashMap<>();
            tradeInfo2.put("from", customerId);
            String linkId = "";
            Integer payMode = mallService.getPayModeByOrgId(orgId);
            if(payMode==2){
                linkId =purchaseProcessDao.getLinkIdByOrgId(orgId);
            }else if(payMode==3){
                linkId = purchaseProcessDao.getLinkIdByLinkOrg("linker");
            }
            tradeInfo2.put("to", linkId);
            tradeInfo2.put("amount", linkerFee);
            tradeInfo2.put("tradeType", 9);
            tradeInfo2.put("payType", 1);
            tradeInfo2.put("receiveRole", 0);
            tradeInfo2.put("accountType", "");
            tradeInfo2.put("receiveAccount", "");
            tradeInfos.add(tradeInfo2);
        }

        if(unionBarleyFee != 0){
            // 支付抽成(大b)
            Map<String, Object> tradeInfo3 = new HashMap<>();
            tradeInfo3.put("from", customerId);
            tradeInfo3.put("orderSn", orderSn);
            tradeInfo3.put("recId", "");
            tradeInfo3.put("to", orgId);
            tradeInfo3.put("amount", unionBarleyFee);
            tradeInfo3.put("tradeType", TradeTypeConstants.PAY_CENTAGE_FEE);
            tradeInfo3.put("payType", 1);
            tradeInfo3.put("receiveRole", 1);
            tradeInfo3.put("accountType", "");
            tradeInfo3.put("receiveAccount", "");
            tradeInfos.add(tradeInfo3);
        }

        Integer processFee = unionBarleyFee + linkerFee;
        if(processFee != 0){
            // 手续费
            Map<String, Object> tradeInfo3 = new HashMap<>();
            tradeInfo3.put("from", toCustomerId);
            tradeInfo3.put("orderSn", orderSn);
            tradeInfo3.put("recId", "");
            tradeInfo3.put("to", "");
            tradeInfo3.put("amount", processFee);
            tradeInfo3.put("tradeType", TradeTypeConstants.TRADE_SERVER_FEE);
            tradeInfo3.put("payType", 1);
            tradeInfo3.put("receiveRole", -1);
            tradeInfo3.put("payRole", toCustomerId.equals(orgId) ? 1 : 2);
            tradeInfo3.put("accountType", "");
            tradeInfo3.put("receiveAccount", "");
            tradeInfos.add(tradeInfo3);
        }

        if(totalPrice != 0){
            // 返润佣金（支出）
            Map<String, Object> tradeInfo3 = new HashMap<>();
            tradeInfo3.put("from", toCustomerId);
            tradeInfo3.put("orderSn", orderSn);
            tradeInfo3.put("recId", "");
            tradeInfo3.put("to", "");
            tradeInfo3.put("amount", totalPrice);
            tradeInfo3.put("tradeType", TradeTypeConstants.REJUVENATE_FEE);
            tradeInfo3.put("payType", 1);
            tradeInfo3.put("receiveRole", -1);
            tradeInfo3.put("payRole", toCustomerId.equals(orgId) ? 1 : 2);
            tradeInfo3.put("accountType", "");
            tradeInfo3.put("receiveAccount", "");
            tradeInfos.add(tradeInfo3);
        }


        Integer income = payAmount;
        // 商品收益
        Map<String, Object> tradeInfo = new HashMap<>();
        tradeInfo.put("from", customerId);
        tradeInfo.put("to", toCustomerId);
        tradeInfo.put("amount", income);
        // 交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费，5-开通联盟商家平台费，6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商城商品平台费，10-商城商品收益，11-提现手续费
        tradeInfo.put("tradeType", TradeTypeConstants.PAY_ENROLL_FEE);
        // 支付方式1-rmb，2-积分
        tradeInfo.put("payType", 1);
        tradeInfo.put("receiveRole", toCustomerId.equals(orgId) ? 1 : 2);
        tradeInfo.put("accountType", "");
//        tradeInfo.put("receiveAccount", belongAccountNumber);
        tradeInfos.add(tradeInfo);

        // 冻结时间
//        Integer freezeTime = purchaseProcessDao.getFreezeTimeByOrgId(orgId);
//        if (freezeTime == null || freezeTime < 0) {
//            freezeTime = 30;
//        }
        // 解冻时间
        String unFreezeTime = df.format(LocalDateTime.now());

        String info = JSON.toJSONString(tradeInfos);
//bug#82613        amqpTemplate.convertAndSend(QueueName.ENROLL_UNFREEZE, info);
//bug#82613        purchaseProcessService.signalAgentPay(orderSn, orgId);

        Map<String, Long> userRoleMap = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
        Map<String, Long> userRoleMap2 = purchaseProcessDao.getUserRoleMapByCustomerId(distributor);
        Long c = userRoleMap.get("c");
        Long c2 = userRoleMap2.get("c");
        if (c == 1 && c2 == 1) {
            // 上级是加盟代理的订单(用于统计数据)
            purchaseProcessDao.insertPromoterOrder(orderSn, 1);
        } else if (c == 1) {
            purchaseProcessDao.insertPromoterOrder(orderSn, 2);
        } else if (c2 == 1) {
            purchaseProcessDao.insertPromoterOrder(orderSn, 3);
        }

        List<TradeInfo> tradeInfoList = JSON.parseArray(info, TradeInfo.class);
        Integer payMode = mallService.getPayModeByOrgId(orgId);
        for (TradeInfo tradeInfoItem : tradeInfoList) {

            Integer payType = tradeInfoItem.getPayType();
            switch (payType) {
                case 1: {
                    // 现金
                    String to = tradeInfoItem.getTo();
                    Integer receiveRole = tradeInfoItem.getReceiveRole();
                    Integer balance;
                    Integer payRole = tradeInfoItem.getPayRole();
                    if(payType.equals(TradeTypeConstants.TRADE_SERVER_FEE) || payType.equals(TradeTypeConstants.REJUVENATE_FEE)){
                        //交易手续费,返润佣金 要扣除冻结金额
                        switch (payRole){
                            case 1:
                                // 大b
                                purchaseProcessDao.reduceOrgAccountFreeze(tradeInfoItem);
                                break;
                            case 2:
                                // 小b
                                purchaseProcessDao.reduceSalesAccountFreeze(tradeInfoItem);
                                break;
                            default:
                                break;
                        }
                    }
                    switch (receiveRole) {
                        // 根据收款人角色，判断给哪个表加，在哪个表查余额。
                        // 先加，再取余额，再记录
                        case 0:
                            balance = 0;
                            break;
                        case 1:
                            // 大b
                            purchaseProcessDao.updateOrgAccountFreeze(tradeInfoItem);
                            balance = purchaseProcessDao.getOrgBalanceByOrgId(to);
                            break;
                        case 2:
                            // 小b
                            purchaseProcessDao.updateSalesAccountFreeze(tradeInfoItem);
                            balance = purchaseProcessDao.getSalesBalanceByCustomerId(to);
                            stringRedisTemplate.delete("home:customer_info_" + to);
                            break;
                        case 3:
                        case 4:
                        case 5:
                            // 普通用户
                            purchaseProcessDao.updateCustomerAccountFreeze(tradeInfoItem);
                            balance = purchaseProcessDao.getUserBalanceByCustomerId(to);
                            stringRedisTemplate.delete("home:customer_info_" + to);
                            break;
                        default:
                            balance = 0;
                            break;
                    }
                    Map<String, Object> map = new HashMap<>();
                    map.put("orgId", orgId);
                    map.put("payMode", payMode);
                    map.put("orderName", title);

                    map.put("balance", balance);
                    map.put("orderSn", orderSn);
                    map.put("tradeInfo", tradeInfoItem);
                    map.put("unFreezeTime", unFreezeTime);
                    // 生成业务单号
                    String busiSn = purchaseProcessService.generateBusiSn(tradeInfoItem.getTradeType(), customerId);
                    map.put("busiSn", busiSn);
                    map.put("serialNo", tradeSn);
                    JSON.toJSONString("insertTradeInfo===" + JSON.toJSONString(map));
//                    purchaseProcessDao.insertTradeInfo(map);
                    purchaseProcessDao.insertProtectTradeInfo(map);

                    break;
                }
                case 2: {
                    // 积分
                    String to = tradeInfoItem.getTo();
//                    Integer receiveRole = tradeInfo.getReceiveRole();
                    Integer balance;
                    if (tradeInfoItem.getTradeType() != 0) {
                        // 0为支出，已在创建时扣除，只需记录
                        purchaseProcessDao.addScoreByCustomerId(tradeInfoItem.getAmount().longValue(), tradeInfoItem.getTo());
                    }
                    balance = purchaseProcessDao.getCustomerScoreBalanceByCustomerId(to);
                    Map<String, Object> map = new HashMap<>();
                    map.put("orgId", orgId);
                    map.put("payMode", payMode);
                    map.put("orderName", title);

                    map.put("balance", balance);
                    map.put("orderSn", orderSn);
                    map.put("tradeInfo", tradeInfoItem);
                    map.put("unFreezeTime", unFreezeTime);
                    // 生成业务单号
                    String busiSn = purchaseProcessService.generateBusiSn(tradeInfoItem.getTradeType(), customerId);
                    map.put("busiSn", busiSn);
                    map.put("serialNo", tradeSn);
//                    purchaseProcessDao.insertTradeScoreInfo(map);
                    purchaseProcessDao.insertProtectTradeInfo(map);
                    break;
                }
                default:
                    break;
            }
        }


    }
    private void saveOrgMoney(Map<String, Object> record) {
        LOGGER.info("saveOrgMoney===" + JSON.toJSONString(record));
        String orderSn = (String) record.get("orderSn");
        String tradeSn = (String) record.get("tradeSn");
        String distributor = (String) record.get("pid");
        String orgId = (String) record.get("orgId");
        String enrollId = (String) record.get("enrollId");
        String customerId = (String) record.get("customerId");
        Integer payAmount = 0;
        if(null != record.get("payAmount")){
            payAmount = Integer.valueOf(record.get("payAmount").toString());
        }
        Map<String, Object> enroll = enrollActiveDao.getInfo(record);
        String toCustomerId = (String) enroll.get("customerId");
        String title = (String) enroll.get("title");
        overViewInfoService.goodsData(null, enrollId, 3, null, null,
                null, 1, payAmount, customerId, orgId,null);
        Map<String, Integer> reverseProfitModel = mallBoomDao.getReverseProfitModel(orgId);// 返润模式
        Integer serviceRatio;// 商品服务费占比例,eg:50
        Integer recommendRatio;// 商品推荐费比例
        Integer originalRatio;// 商品创作费比例
        Integer unhappen;// 未产生费用给谁 1-商家2-机构
        if (reverseProfitModel == null) {
            // 机构没有设置返润模式
            serviceRatio = 50;
            recommendRatio = 50;
            originalRatio = 0;
            unhappen = 1;
        } else {
            serviceRatio = reverseProfitModel.get("serviceRatio");
            recommendRatio = reverseProfitModel.get("recommendRatio");
            originalRatio = reverseProfitModel.get("originalRatio");
            unhappen = reverseProfitModel.get("unhappen");
        }
        String rebateStr = enrollActiveDao.getRebateByEnrollId(enrollId);
        if (StringUtils.isEmpty(rebateStr)) {
            rebateStr = "0";
        }
        Double rebate = Double.valueOf(rebateStr);
        if(!StringUtils.isEmpty(distributor)){
            //异步
            Map clueMap = new HashMap();
            clueMap.put("promoterId",distributor);
            clueMap.put("customerId",customerId);
            clueMap.put("actionType",11);
            clueMap.put("relevantId",enrollId);
            clueMap.put("relevantName",title);
            clueMap.put("amount",NumberUtils.fenToYuan(Long.parseLong(payAmount.toString())));
            clueMap.put("orderSn",orderSn);
            clueMap.put("type",2);
            clueMap.put("orgId",orgId);
            //增加销售线索
            promoterClueService.addClue(clueMap);
        }
        double i = rebate * serviceRatio.doubleValue() / 100;// 服务费比例,eg:10
        double j = rebate * recommendRatio.doubleValue() / 100;// 推荐费比例,eg:10
        double k = rebate * originalRatio.doubleValue() / 100;  // 创作费比例,eg:10
        double iv = payAmount.doubleValue() * i / 100;// 服务费
        double jv = payAmount.doubleValue() * j / 100;// 推荐费
        double kv =payAmount.doubleValue() * k / 100; // 创作费
        int sharePrice = new BigDecimal(iv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(服务费)1
        int recomPrice = new BigDecimal(jv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 返利值(推荐费)2
        int originalPrice = new BigDecimal(kv).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();        // 返利值(创作费)3
        double goodsAllRebate = payAmount.doubleValue() * rebate / 100;// 总返利
        int totalPrice = new BigDecimal(goodsAllRebate).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();// 总返利值
        int platformPrice = totalPrice - sharePrice - recomPrice-originalPrice;// 返利值(平台费)3
        if (platformPrice < 0) {
            // 推荐费服务费创作费都进位，平台费为0，导致总返利减去推荐费和服务费结果为-1，需要调整费用
            platformPrice = 0;
            if(totalPrice - recomPrice- originalPrice>0){
                sharePrice= totalPrice - recomPrice- originalPrice;
            }else if(totalPrice - recomPrice>0){
                sharePrice = 0;
                recomPrice = totalPrice - recomPrice;
            }
        }
        Map<String, String> platformRateMap = purchaseProcessDao.getPlatformRateByOrgId(orgId);
        // lh抽成
        Double linkerTake = Double.valueOf(platformRateMap.get("linkerTake"));
        // 大b抽成
        Double unionBarleyTake = Double.valueOf(platformRateMap.get("unionBarleyTake"));

        double v2 = payAmount * linkerTake / 100;
        int linkerFee = new BigDecimal(v2).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        double v3 = payAmount * unionBarleyTake / 100;
        int unionBarleyFee = new BigDecimal(v3).setScale(0, BigDecimal.ROUND_HALF_EVEN).intValue();
        // 平台费3
        int platformFee = linkerFee + unionBarleyFee;


        String pid = purchaseProcessDao.getPidByCid(customerId);
        // 是否产出推荐费给推荐人
        boolean ifRf = !StringUtils.isEmpty(pid) && recomPrice != 0 && !pid.equals(customerId);
        if (!StringUtils.isEmpty(pid)) {
            // 推广员不返推荐费
            Map<String, Long> role = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
            Long a = role.get("a");
            Long b = role.get("b");
            Long c = role.get("c");
            if (a == 0 && b == 1 && c == 0) {
                ifRf = false;
            }
            if (c == 0) {
                ifRf = false;
            }
        }
        // 是否产出服务费给分享人
        boolean ifFw = !StringUtils.isEmpty(distributor) && sharePrice != 0 && !distributor.equals(customerId);

        boolean distributorIsNormal = false;
        if (ifFw) {
            distributorIsNormal = purchaseProcessService.getUserRole(distributor);
        }

        Integer unhappenFee = originalPrice;
        List<Map<String, Object>> tradeInfos = new ArrayList<>();
        if (ifFw && ifRf) {
            // 服务
            Map<String, Object> tradeInfo1 = new HashMap<>();
            tradeInfo1.put("from", customerId);
            tradeInfo1.put("to", distributor);
            tradeInfo1.put("amount", sharePrice);
            // 积分交易类型0-金币抵扣，1-商品服务费，2 -金币退回
            tradeInfo1.put("tradeType", distributorIsNormal ? 1 : 2);
            // 支付方式1-rmb，2-积分
            tradeInfo1.put("payType", distributorIsNormal ? 2 : 1);
            tradeInfo1.put("receiveRole", 5);
            tradeInfo1.put("accountType", "");
            tradeInfo1.put("receiveAccount", "");
            tradeInfos.add(tradeInfo1);
            // 推荐
            Map<String, Object> tradeInfo2 = new HashMap<>();
            tradeInfo2.put("from", customerId);
            tradeInfo2.put("to", pid);
            tradeInfo2.put("amount", recomPrice);
            // 交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费，5-开通联盟商家平台费，6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商城商品平台费，10-商城商品收益，11-提现手续费
            tradeInfo2.put("tradeType", 3);
            tradeInfo2.put("payType", 1);
            tradeInfo2.put("receiveRole", 5);
            tradeInfo2.put("accountType", "");
            tradeInfo2.put("receiveAccount", "");
            tradeInfos.add(tradeInfo2);
        } else if (ifFw) {
            // 仅服务费
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("to", distributor);
            tradeInfo.put("amount", sharePrice);
            tradeInfo.put("tradeType", distributorIsNormal ? 1 : 2);
            tradeInfo.put("payType", distributorIsNormal ? 2 : 1);
            tradeInfo.put("receiveRole", 5);
            tradeInfo.put("accountType", "");
            tradeInfo.put("receiveAccount", "");
            tradeInfos.add(tradeInfo);
            unhappenFee += recomPrice;

        } else if (ifRf) {
            // 仅推荐费
            Map<String, Object> tradeInfo = new HashMap<>();
            tradeInfo.put("from", customerId);
            tradeInfo.put("to", pid);
            tradeInfo.put("amount", recomPrice);
            tradeInfo.put("tradeType", 3);
            tradeInfo.put("payType", 1);
            tradeInfo.put("receiveRole", 5);
            tradeInfo.put("accountType", "");
            tradeInfo.put("receiveAccount", "");
            tradeInfos.add(tradeInfo);
            unhappenFee += sharePrice;
        } else {
            // 两笔钱都无人认领
            unhappenFee += recomPrice + sharePrice;
        }
//        Integer income = payAmount - totalPrice - platformFee;
        if (unhappen == 1) {
//            income += unhappenFee;
            totalPrice -= unhappenFee;
        } else if (unhappen == 2 && unhappenFee > 0) {
            // 未产生费用给平台
//            unionBarleyFee += unhappenFee;
            platformPrice += unhappenFee;
        }
//        unionBarleyFee += platformPrice;
        if (platformPrice != 0) {
            // 大b平台费
            Map<String, Object> tradeInfo1 = new HashMap<>();
            tradeInfo1.put("from", customerId);
            tradeInfo1.put("to", orgId);
//            tradeInfo1.put("amount", unionBarleyFee);
            tradeInfo1.put("amount", platformPrice);
            tradeInfo1.put("tradeType", 4);
            tradeInfo1.put("payType", 1);
            tradeInfo1.put("receiveRole", 1);
            tradeInfo1.put("accountType", "");
            tradeInfo1.put("receiveAccount", "");
            tradeInfos.add(tradeInfo1);
        }
        if (linkerFee != 0) {
            // 联汇平台费
            Map<String, Object> tradeInfo2 = new HashMap<>();
            tradeInfo2.put("from", customerId);
            String linkId = "";
            Integer payMode = mallService.getPayModeByOrgId(orgId);
            if(payMode==2){
                linkId =purchaseProcessDao.getLinkIdByOrgId(orgId);
            }else if(payMode==3){
                linkId = purchaseProcessDao.getLinkIdByLinkOrg("linker");
            }
            tradeInfo2.put("to", linkId);
            tradeInfo2.put("amount", linkerFee);
            tradeInfo2.put("tradeType", 9);
            tradeInfo2.put("payType", 1);
            tradeInfo2.put("receiveRole", 0);
            tradeInfo2.put("accountType", "");
            tradeInfo2.put("receiveAccount", "");
            tradeInfos.add(tradeInfo2);
        }

        if(unionBarleyFee != 0){
            // 支付抽成(大b)
            Map<String, Object> tradeInfo3 = new HashMap<>();
            tradeInfo3.put("from", customerId);
            tradeInfo3.put("orderSn", orderSn);
            tradeInfo3.put("recId", "");
            tradeInfo3.put("to", orgId);
            tradeInfo3.put("amount", unionBarleyFee);
            tradeInfo3.put("tradeType", TradeTypeConstants.PAY_CENTAGE_FEE);
            tradeInfo3.put("payType", 1);
            tradeInfo3.put("receiveRole", 1);
            tradeInfo3.put("accountType", "");
            tradeInfo3.put("receiveAccount", "");
            tradeInfos.add(tradeInfo3);
        }

        Integer processFee = unionBarleyFee + linkerFee;
        if(processFee != 0){
            // 手续费
            Map<String, Object> tradeInfo3 = new HashMap<>();
            tradeInfo3.put("from", toCustomerId);
            tradeInfo3.put("orderSn", orderSn);
            tradeInfo3.put("recId", "");
            tradeInfo3.put("to", "");
            tradeInfo3.put("amount", processFee);
            tradeInfo3.put("tradeType", TradeTypeConstants.TRADE_SERVER_FEE);
            tradeInfo3.put("payType", 1);
            tradeInfo3.put("receiveRole", -1);
            tradeInfo3.put("payRole", toCustomerId.equals(orgId) ? 1 : 2);
            tradeInfo3.put("accountType", "");
            tradeInfo3.put("receiveAccount", "");
            tradeInfos.add(tradeInfo3);
        }

        if(totalPrice != 0){
            // 返润佣金（支出）
            Map<String, Object> tradeInfo3 = new HashMap<>();
            tradeInfo3.put("from", toCustomerId);
            tradeInfo3.put("orderSn", orderSn);
            tradeInfo3.put("recId", "");
            tradeInfo3.put("to", "");
            tradeInfo3.put("amount", totalPrice);
            tradeInfo3.put("tradeType", TradeTypeConstants.REJUVENATE_FEE);
            tradeInfo3.put("payType", 1);
            tradeInfo3.put("receiveRole", -1);
            tradeInfo3.put("payRole", toCustomerId.equals(orgId) ? 1 : 2);
            tradeInfo3.put("accountType", "");
            tradeInfo3.put("receiveAccount", "");
            tradeInfos.add(tradeInfo3);
        }


        Integer income = payAmount;
        // 商品收益
        Map<String, Object> tradeInfo = new HashMap<>();
        tradeInfo.put("from", customerId);
        tradeInfo.put("to", toCustomerId);
        tradeInfo.put("amount", income);
        // 交易类型：0-提现，1-商品成交收益，2-商品服务费，3-商品推荐费，4-商品平台费，5-开通联盟商家平台费，6-开通联盟商家收益，7-开通加盟代理平台费，8-开通加盟代理收益，9-商城商品平台费，10-商城商品收益，11-提现手续费
        tradeInfo.put("tradeType", 1);
        // 支付方式1-rmb，2-积分
        tradeInfo.put("payType", 1);
        tradeInfo.put("receiveRole", toCustomerId.equals(orgId) ? 1 : 2);
        tradeInfo.put("accountType", "");
//        tradeInfo.put("receiveAccount", belongAccountNumber);
        tradeInfos.add(tradeInfo);

        // 冻结时间
//        Integer freezeTime = purchaseProcessDao.getFreezeTimeByOrgId(orgId);
//        if (freezeTime == null || freezeTime < 0) {
//            freezeTime = 30;
//        }
        // 解冻时间
        String unFreezeTime = df.format(LocalDateTime.now());

        String info = JSON.toJSONString(tradeInfos);
//bug#82613        amqpTemplate.convertAndSend(QueueName.ENROLL_UNFREEZE, info);
//bug#82613        purchaseProcessService.signalAgentPay(orderSn, orgId);

        Map<String, Long> userRoleMap = purchaseProcessDao.getUserRoleMapByCustomerId(pid);
        Map<String, Long> userRoleMap2 = purchaseProcessDao.getUserRoleMapByCustomerId(record.get("pid").toString());
        Long c = userRoleMap.get("c");
        Long c2 = userRoleMap2.get("c");
        if (c == 1 && c2 == 1) {
            // 上级是加盟代理的订单(用于统计数据)
            purchaseProcessDao.insertPromoterOrder(orderSn, 1);
        } else if (c == 1) {
            purchaseProcessDao.insertPromoterOrder(orderSn, 2);
        } else if (c2 == 1) {
            purchaseProcessDao.insertPromoterOrder(orderSn, 3);
        }

        List<TradeInfo> tradeInfoList = JSON.parseArray(info, TradeInfo.class);
        Integer payMode = mallService.getPayModeByOrgId(orgId);
        for (TradeInfo tradeInfoItem : tradeInfoList) {

            Integer payType = tradeInfoItem.getPayType();
            switch (payType) {
                case 1: {
                    // 现金
                    String to = tradeInfoItem.getTo();
                    Integer receiveRole = tradeInfoItem.getReceiveRole();
                    Integer balance;
                    Integer payRole = tradeInfoItem.getPayRole();
                    if(payType.equals(TradeTypeConstants.TRADE_SERVER_FEE) || payType.equals(TradeTypeConstants.REJUVENATE_FEE)){
                        //交易手续费,返润佣金 要扣除冻结金额
                        switch (payRole){
                            case 1:
                                // 大b
                                purchaseProcessDao.reduceOrgAccountFreeze(tradeInfoItem);
                                break;
                            case 2:
                                // 小b
                                purchaseProcessDao.reduceSalesAccountFreeze(tradeInfoItem);
                                break;
                            default:
                                break;
                        }
                    }
                    switch (receiveRole) {
                        // 根据收款人角色，判断给哪个表加，在哪个表查余额。
                        // 先加，再取余额，再记录
                        case 0:
                            balance = 0;
                            break;
                        case 1:
                            // 大b
                            purchaseProcessDao.updateOrgAccountFreeze(tradeInfoItem);
                            balance = purchaseProcessDao.getOrgBalanceByOrgId(to);
                            break;
                        case 2:
                            // 小b
                            purchaseProcessDao.updateSalesAccountFreeze(tradeInfoItem);
                            balance = purchaseProcessDao.getSalesBalanceByCustomerId(to);
                            stringRedisTemplate.delete("home:customer_info_" + to);
                            break;
                        case 3:
                        case 4:
                        case 5:
                            // 普通用户
                            purchaseProcessDao.updateCustomerAccountFreeze(tradeInfoItem);
                            balance = purchaseProcessDao.getUserBalanceByCustomerId(to);
                            stringRedisTemplate.delete("home:customer_info_" + to);
                            break;
                        default:
                            balance = 0;
                            break;
                    }
                    Map<String, Object> map = new HashMap<>();
                    map.put("orgId", orgId);
                    map.put("payMode", payMode);
                    map.put("orderName", title);

                    map.put("balance", balance);
                    map.put("orderSn", orderSn);
                    map.put("tradeInfo", tradeInfoItem);
                    map.put("unFreezeTime", unFreezeTime);
                    // 生成业务单号
                    String busiSn = purchaseProcessService.generateBusiSn(tradeInfoItem.getTradeType(), customerId);
                    map.put("busiSn", busiSn);
                    map.put("serialNo", tradeSn);
                    JSON.toJSONString("insertTradeInfo===" + JSON.toJSONString(map));
//                    purchaseProcessDao.insertTradeInfo(map);
                    purchaseProcessDao.insertProtectTradeInfo(map);

                    break;
                }
                case 2: {
                    // 积分
                    String to = tradeInfoItem.getTo();
//                    Integer receiveRole = tradeInfo.getReceiveRole();
                    Integer balance;
                    if (tradeInfoItem.getTradeType() != 0) {
                        // 0为支出，已在创建时扣除，只需记录
                        purchaseProcessDao.addScoreByCustomerId(tradeInfoItem.getAmount().longValue(), tradeInfoItem.getTo());
                    }
                    balance = purchaseProcessDao.getCustomerScoreBalanceByCustomerId(to);
                    Map<String, Object> map = new HashMap<>();
                    map.put("orgId", orgId);
                    map.put("payMode", payMode);
                    map.put("orderName", title);

                    map.put("balance", balance);
                    map.put("orderSn", orderSn);
                    map.put("tradeInfo", tradeInfoItem);
                    map.put("unFreezeTime", unFreezeTime);
                    // 生成业务单号
                    String busiSn = purchaseProcessService.generateBusiSn(tradeInfoItem.getTradeType(), customerId);
                    map.put("busiSn", busiSn);
                    map.put("serialNo", tradeSn);
//                    purchaseProcessDao.insertTradeScoreInfo(map);
                    purchaseProcessDao.insertProtectTradeInfo(map);
                    break;
                }
                default:
                    break;
            }
        }


    }

    /**
     * 报名状态
     *
     * @param enrollId
     * @return 0 报名关闭 1 待报名 2 报名结束 3 报名已满 4 报名中
     */
    public int getEnrollStatus(String enrollId) {
        Map<String, Object> param = new HashMap<>();
        param.put("enrollId", enrollId);

        Map<String, Object> info = enrollActiveDao.getInfo(param);
        if (info == null) {
            return 0;
        }
        String startTime = null;
        if (!StringUtils.isEmpty(info.get("startTime"))) {
            startTime = info.get("startTime").toString();
        }
        String endTime = null;
        if (!StringUtils.isEmpty(info.get("endTime"))) {
            endTime = info.get("endTime").toString();
        }
        String status = (String) info.get("status");

        String nowTime = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
        // 获取已报名人数
        Integer realNum = enrollActiveDao.getRealNum(enrollId);
        // 获取设置的报名总人数 减去 初始化的总人数
        Integer setNum = enrollActiveDao.getSetNum(enrollId);
        // 获取是否存在不限人数的报名项
        Integer unlimited = enrollActiveDao.unlimited(enrollId);
        if ("0".equals(status)) {
            // 报名关闭
            return 0;
        } else if (!StringUtils.isEmpty(startTime) && nowTime.compareTo(startTime) < 0) {
            // 待报名
            return 1;
        } else if (!StringUtils.isEmpty(endTime) && nowTime.compareTo(endTime) > 0) {
            // 报名结束
            return 2;
        } else if (unlimited < 1 && realNum >= setNum) {
            // 报名已满
            return 3;
        } else {
            //报名中
            return 4;
        }
    }

    public Map payRecord(Map<String, Object> param) {
        String orderSn = param.get("orderSn").toString();
        String openId = param.get("openId").toString();
        Map<String, Object> customerRecord = enrollActiveDao.getCustomerRecordByOrderSn(orderSn);
        if(null == customerRecord || customerRecord.isEmpty()) {
            customerRecord = (Map) this.formRequest.doRequest("/h5/form/getRecordByOrderSn", param, null);
            LOGGER.info("customerRecord: " + JSON.toJSONString(customerRecord));
            Integer payMode = mallDao.getPayModeByOrgId(customerRecord);
            int totalFee = Integer.valueOf(customerRecord.get("payAmount").toString());
            String orgId = customerRecord.get("orgId").toString();
            String rebateStr = customerRecord.get("rebateStr").toString();
            String customerId = customerRecord.get("customerId").toString();
            String distributor = customerRecord.get("distributor").toString();
            String createCustomerId = customerRecord.get("createCustomerId").toString();
            String title = customerRecord.get("title").toString();
            String s = this.tlPayDetail(totalFee, orgId, rebateStr, customerId, distributor, orderSn, openId, "2", payMode, distributor, createCustomerId, title, "");
            Map resultMap = (Map) JSON.parse(s);
            resultMap.put("orderSn", orderSn);
            resultMap.put("orgId", orgId);
            resultMap.put("recordPid", distributor);
            resultMap.put("customerId", customerId);
            String enrollNotifyUrl = formUrl + "/h5/form/payCallback";//支付回调地址
            stringRedisTemplate.opsForValue().set("enrollrecord:getsign_" + orderSn, JSON.toJSONString(resultMap), 1, TimeUnit.DAYS);
            stringRedisTemplate.opsForValue().set("enrollrecord:key_" + orderSn, JSON.toJSONString(customerRecord), 365, TimeUnit.DAYS);
            stringRedisTemplate.opsForValue().set("enrollnotify:key_" + orderSn, enrollNotifyUrl, 365, TimeUnit.DAYS);
            return resultMap;
        }else {
            Integer payMode = mallDao.getPayModeByOrgId(customerRecord);
            // 通联支付
            String frontUrl = "";
            if (!StringUtils.isEmpty(param.get("frontUrl"))) {
                frontUrl = param.get("frontUrl").toString();
            }
            String s = this.tlPay(Integer.valueOf(customerRecord.get("payAmount").toString()), customerRecord.get("orgId").toString(), customerRecord.get("enrollId").toString(), customerRecord.get("customerId").toString(), customerRecord.get("pid").toString(), orderSn, openId, 2, payMode, customerRecord.get("id").toString(), frontUrl);
            LOGGER.info("payRecord: " + s);
            Map resultMap = (Map) JSON.parse(s);
            // noinspection unchecked
            resultMap.put("orderSn", orderSn);
            return resultMap;
        }

    }

    public Map<String, Object> getCustomerRecordMap(Map<String, Object> param) {
        return enrollActiveDao.getCustomerRecordMap(param);
    }
}
